package com.ztp.pc.gui.fileview;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DropMode;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.table.TableRowSorter;

import com.ztp.lib.files.DirectoryChangeListener;
import com.ztp.lib.files.DisplayableExplorer;
import com.ztp.lib.files.DisplayableFile;
import com.ztp.pc.gui.gtabpane.GTabPane;

import static java.lang.System.out;

public class FilePanel extends JPanel {
	private static final long serialVersionUID = -3457203668187249028L;
	
	public GTabPane tabPane;
	JScrollPane scrollPane;
	JTable table;
	FileTableModel fileTableModel;
	TableRowSorter<FileTableModel> rowSorter;
	JComboBox<String> rootsComboBox;
	
	DisplayableExplorer mExplorer;
	
	JTextField addressBar, filterBar;
	
	public FilePanel(DisplayableExplorer explorer){
		super();
		this.setLayout(new BorderLayout());
		//this.setBackground(Color.red);
		
		mExplorer = explorer;
		mExplorer.addDirectoryChangeListener(new DirectoryChangeListener() {
			@Override
			public void directoryChanged( DisplayableFile currDir) {
				setAddress();
			}

			@Override
			public void rootChanged(DisplayableFile root) {
				out.println("rootChanged" + root);
				rootsComboBox.setSelectedItem(root.absPath);
			}
		});
		
		
		fileTableModel = new FileTableModel(mExplorer);
		rowSorter = new TableRowSorter<FileTableModel>(fileTableModel);
		rowSorter.setComparator(0, DisplayableFile.BY_FILE_NAME);
		table = new JTable(fileTableModel);
		table.getColumnModel().getColumn(0).setCellRenderer(new FileIconAndNameCellRenderer());
		table.setDragEnabled(true);
		table.setDropMode(DropMode.INSERT_ROWS);
		table.setShowHorizontalLines(false);
		table.setAutoCreateRowSorter(true);
		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				if(SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2){
					int row = table.rowAtPoint(e.getPoint());
					try{
						mExplorer.setDirectory(table.convertRowIndexToModel(row));
					}
					catch(Exception ex){
						JOptionPane.showMessageDialog(null
								, ex.getMessage()
								, "Error"
								, JOptionPane.ERROR_MESSAGE);
					}
				}
				else{
					super.mousePressed(e);
				}
			}
		});
		table.setRowSorter(rowSorter);
		
		scrollPane = new JScrollPane();
		scrollPane.setViewportView(table);
		
		this.add(scrollPane);
		
		
		addressBar = new JTextField();
		addressBar.addKeyListener(new KeyListener() {
			@Override
			public void keyTyped(KeyEvent e) {}
			@Override
			public void keyReleased(KeyEvent e) {}
			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == 10){
					try{
						if(!mExplorer.tryToChangeDirectory(addressBar.getText())){
							addressBar.setText(mExplorer.getCurrentDirAbsPath());//ustaw poprzedni poprawny path
						}
					}
					catch(Exception exc){
						JOptionPane.showMessageDialog(null
								, exc.getMessage()
								, "Error"
								, JOptionPane.ERROR_MESSAGE);
						addressBar.setText(mExplorer.getCurrentDirAbsPath());
					}
				}
			}
		});
		setAddress();
		
		filterBar = new JTextField();
		filterBar.getDocument().addDocumentListener(filterDocumentListener);
		
		JPanel panelNorth = new JPanel();
		panelNorth.setLayout(new BorderLayout(0, 0));
		panelNorth.add(addressBar, BorderLayout.NORTH);
			JPanel filterPanel = new JPanel(new BorderLayout());
			filterPanel.add(new JLabel("Filter:"), BorderLayout.WEST);
			filterPanel.add(filterBar, BorderLayout.CENTER);
			
			rootsComboBox = new JComboBox<String>(mExplorer.getRootsPath());
			rootsComboBox.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					//out.println("actionPerformed " + rootsComboBox.getSelectedItem().toString());
					mExplorer.changeRoot((String) rootsComboBox.getSelectedItem());
				}
			});
			rootsComboBox.setToolTipText("Roots");
			
			
			JPanel buttonsPanel = new JPanel(new BorderLayout());
			buttonsPanel.add(rootsComboBox);
			
		panelNorth.add(buttonsPanel, BorderLayout.CENTER);
		panelNorth.add(filterPanel, BorderLayout.SOUTH);
		
		filterBar.setMinimumSize(filterBar.getMaximumSize());
		
		this.add(panelNorth, BorderLayout.NORTH);
		
	}
	
	private void setAddress(){
		addressBar.setText(mExplorer.getCurrentDirAbsPath() );//+ File.separator
	}
	
	private void filterFileNameCol(){
		String text = filterBar.getText();
		//System.out.println("filtering " + text);
		if(text.length() != 0){
			rowSorter.setRowFilter(fileNameFilter);
		}
		else{
			rowSorter.setRowFilter(null);
		}
	}
	
	private final RowFilter<FileTableModel, Object> fileNameFilter = new RowFilter<FileTableModel, Object>(){
		@Override
		public boolean include(javax.swing.RowFilter.Entry<? extends FileTableModel, ? extends Object> entry) {
			DisplayableFile df = (DisplayableFile)entry.getValue(0);
			return df.name.matches("(?i:.*"+filterBar.getText()+".*)");
		}
	};
	
	final DelayedFilter filterDocumentListener = new DelayedFilter();
	
	class DelayedFilter implements DocumentListener, Runnable{
		static final String LOG = "DelayedFilter::";
		
		int value;
		@Override
		public void run() {
			int i;
			synchronized (this) {
				i = ++value;
			}
			
			try {Thread.sleep(800);} 
			catch (InterruptedException e) {e.printStackTrace();}
			
			synchronized (this) {
				if(i == value) FilePanel.this.filterFileNameCol();
			}
		}
		
		private synchronized void fire(){
			new Thread(this).start();
		}

		@Override
		public void changedUpdate(DocumentEvent e) {
			fire();
		}

		@Override
		public void insertUpdate(DocumentEvent e) {
			fire();
		}

		@Override
		public void removeUpdate(DocumentEvent e) {
			fire();
		}
	}
}
